// userexits.cpp
// Customizer
// Protea Customizer / Business Logic for managing user exits
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Please send correspondence to:
//
// theproteaproject@gmail.com
//

#include "customizer.h"

//////////////////////////////////////////////////////////////////////////////
//
// USER_EXIT_DEFNS Transactions
//
//////////////////////////////////////////////////////////////////////////////

//@ SEC 2
//@ CHA Change User Exit
//@ COD ChangeUserExit
//@ NUM 38
//@ CRI USER_EXIT_NAME
//@ CRI TRANS_CODE
//@ GEN Change User Exit will add a user exit for an application
TRANSACTION_CODE( ChangeUserExit )
{
	XCBuffer* buf = NULL;
	XCBuffer* OrigBuf = NULL;

	bool ReviewOnly = true;

	//@ GRS Start the transaction
	START_TXN( ChangeUserExit );

		//@ If critical fields are blank, then
		//@ ERR E (ERR_IS_BLANK) (Field Name) cannot be blank
		if ( txnvars.buffer->GetField( FLD_USER_EXIT_NAME )->IsBlank() )
			txnvars.Errors->Add( ERR_IS_BLANK, SEV_ERROR, FLD_USER_EXIT_NAME, 1, txnvars.buffer->GetField( FLD_USER_EXIT_NAME ) );
		if ( txnvars.buffer->GetField( FLD_APPL_NBR )->IsBlank() )
			txnvars.Errors->Add( ERR_IS_BLANK, SEV_ERROR, FLD_APPL_NBR, 1, txnvars.buffer->GetField( FLD_APPL_NBR ) );

		ReviewOnly = txnvars.buffer->IsBlank( 2, FLD_USER_EXIT_NAME, FLD_APPL_NBR );

		if (!ReviewOnly) {
			if ( txnvars.buffer->GetField( FLD_TRANS_CODE )->IsBlank() )
				txnvars.Errors->Add( ERR_IS_BLANK, SEV_ERROR, FLD_TRANS_CODE, 1, txnvars.buffer->GetField( FLD_TRANS_CODE ) );
		};
		txnvars.Errors->Check();

		//@ Create transaction buffer
		buf = App->CreateBuffer( FMT_USER_EXIT_DEFNS );

		//@ Move screen info to transaction buffer
		buf->MoveCorresponding( txnvars.buffer, txnvars.Errors );
		txnvars.Errors->Check();

		START_DB_TXN();

			OrigBuf = buf->Copy();

			//@ SUB UserExitDefnsVerify to verify that user exit can be modified
			UserExitDefnsVerify( buf, ReviewOnly ? VERIFY_REVIEW : VERIFY_CHANGE, &txnvars, OrigBuf );

			//@ Check for errors
			txnvars.Errors->Check();

			if (!ReviewOnly) {
				OrigBuf->MoveField( buf, FLD_USER_EXIT_NUMBER );

				//@ SUB UserExitDefnsChange to alter the user exit
				UserExitDefnsChange( OrigBuf, buf, &txnvars );

				LOG_TRANSACTION();
			} else {
				//@ Lookup TRANS_CODE from TRANS_NUMBER
				if (!LookupNameFromNumber( &txnvars, buf, txnvars.buffer, FLD_TRANS_NUMBER, FLD_TRANS_CODE, FMT_TRANSACTION_DEFN ) )
					txnvars.buffer->GetField( FLD_TRANS_CODE )->Clear();
			};

		END_DB_TXN();

		//@ Send back result buffer
		if (ReviewOnly)
			txnvars.buffer->MoveCorresponding( buf, txnvars.Errors );
		else
			txnvars.buffer->MoveCorresponding( OrigBuf, txnvars.Errors );
		App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

	CLEANUP_TXN();
		App->CleanupObjects( 2, &buf, &OrigBuf );
	END_TXN();
	//@ GRE End the transaction
};



//
//@ CHA RevUserExit
//@ COD RevUserExit
//@ NUM 190
//@ CRI APPL_NBR
//@ TAB USER_EXIT_FMTS Read
//@ TAB USER_EXIT_DEFNS Read
//
//@ GEN RevUserExits returns a list of currently available user exits.  If a user
//@ GEN code is specified, only formats for that user exit will be returned.  If a
//@ GEN Transaction code is given, only user exits for that trans code are returned
//
TRANSACTION_CODE( RevUserExit ) {
	XCBuffer* TransBuf = NULL;
	XCBuffer* detail = NULL;
	XCDBStatement* stmt = NULL;

	//@ GRS Start the transaction
	START_TXN( RevUserExit );
		//@ Create format descriptor buffer
		TransBuf = App->CreateBuffer( FMT_USER_EXIT_DEFNS, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		//@ Start the database transaction
		START_DB_TXN();
			XCCompare comptemp;

			TransBuf->DebugDump();
			App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

			int child = txnvars.buffer->GetChildFormat();
			if (child) {
				detail = App->CreateBuffer( child, true );

				XCField* transcode = detail->GetField( FLD_TRANS_CODE );
				XCField* transnum = TransBuf->GetField( FLD_TRANS_NUMBER );

				// Get the results
				stmt = UserExitList( TransBuf, &txnvars );

				// Loop through the results
				while (!stmt->Eof()) {
					txnvars.Errors->NextBuffer();
					detail->MoveCorresponding( TransBuf, txnvars.Errors, true );

					if (transcode) {
						transcode->Clear();
						if (transnum->GetLong( true ) > 0) {
							LookupNameFromNumber( &txnvars, TransBuf, detail, FLD_TRANS_NUMBER, FLD_TRANS_CODE, FMT_TRANSACTION_DEFN );
						};
					};

					App->TransResponse( txnvars.result, detail, TRANS_DETAIL_TYPE );
					stmt->MoveNext();
				};
			};

		END_DB_TXN();

	CLEANUP_TXN();
		App->CleanupObjects( 3, &TransBuf, &detail, &stmt );
	END_TXN();
	//@ GRE End the transaction
};







//@ SEC 2
//@ CHA Assign User Exit
//@ COD AssignUserExit
//@ NUM 150
//@ CRI USER_EXIT_NAME
//@ CRI TRANS_CODE
//@ GEN Change User Exit will add a user exit for an application
TRANSACTION_CODE( AssignUserExit )
{
	XCBuffer* buf = NULL;
	XCBuffer* OrigBuf = NULL;

	//@ GRS Start the transaction
	START_TXN( ChangeUserExit );

		//@ If critical fields are blank, then
		//@ ERR E (ERR_IS_BLANK) (Field Name) cannot be blank
		if ( txnvars.buffer->GetField( FLD_USER_EXIT_NAME )->IsBlank() )
			txnvars.Errors->Add( ERR_IS_BLANK, SEV_ERROR, FLD_USER_EXIT_NAME, 1, txnvars.buffer->GetField( FLD_USER_EXIT_NAME ) );
		if ( txnvars.buffer->GetField( FLD_APPL_NBR )->IsBlank() )
			txnvars.Errors->Add( ERR_IS_BLANK, SEV_ERROR, FLD_APPL_NBR, 1, txnvars.buffer->GetField( FLD_APPL_NBR ) );
		txnvars.Errors->Check();

		//@ Create transaction buffer
		buf = App->CreateBuffer( FMT_USER_EXIT_DEFNS );

		//@ Move screen info to transaction buffer
		buf->MoveCorresponding( txnvars.buffer, txnvars.Errors );
		txnvars.Errors->Check();

		START_DB_TXN();
			//@ SUB LookupNumberFromName to verify that we do have a user-exit with this name
			//@ ERR C (DOESNT_EXIST) User exit doesn't exist
			if ( ! LookupNumberFromName( &txnvars, txnvars.buffer, buf, FLD_USER_EXIT_NUMBER, FLD_USER_EXIT_NAME, FMT_USER_EXIT_DEFNS ) || !UserExitDefnsRetrieve( buf, &txnvars ))
				txnvars.Errors->Add( ERR_DOESNT_EXIST, SEV_CRITICAL, FLD_USER_EXIT_NAME, 1, ERR_USER_EXIT );

			//@ Make a copy of the transaction buffer, for comparison
			OrigBuf = buf->Copy();

			//@ Lookup transaction number from transaction code (verify it exists)
			if ( ! LookupNumberFromName( &txnvars, txnvars.buffer, buf, FLD_TRANS_NUMBER, FLD_TRANS_CODE, FMT_TRANSACTION_DEFN ) )
				buf->GetField( FLD_TRANS_NUMBER )->Clear();

			//@ Write new user exit record
			UserExitDefnsChange( buf, OrigBuf, &txnvars );

			LOG_TRANSACTION();

		END_DB_TXN();

		txnvars.buffer->MoveCorresponding( buf, txnvars.Errors );
		App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

	CLEANUP_TXN();
		App->CleanupObjects( 2, &buf, &OrigBuf );
	END_TXN();
	//@ GRE End the transaction
};
